﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;
using System.IO;
using System.Drawing.Drawing2D;
using FunctionalLayer;
using ControlLayer;
using SEMAuto.Properties;

namespace SEMAuto
{
    public partial class Form1 : Form
    {
        private ConfigurationForm _configForm;
        private LapConfiguration _configLap;
        private CarController _carController;
        private bool _carInitiated;
        private bool _manualOverride;
        private bool _overheatMessageSend;

        public Form1()
        {
            InitializeComponent();

            //For handling keyboard buttons
            this.KeyPreview = true;

            this.Location = new Point(0, 0);
            this.Bounds = Screen.PrimaryScreen.Bounds;

            setIcons();

            _carInitiated = false;
            _manualOverride = false;

            _configForm = new ConfigurationForm();
            _configLap = new LapConfiguration(_carController);
        }

        /// <summary>
        /// Press button on keyboard to control software
        /// Added for driver convenience
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="keyData"></param>
        /// <returns></returns>
        protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
        {
            if (keyData == (Keys.Enter))
            {
                try
                {
                    tsmInit.PerformClick();
                    _carController.StartLogging();
                    tsmStartLogging.Enabled = false;
                    tsmStopLogging.Enabled = true;
                }
                catch (System.NullReferenceException)
                {
                    MessageBox.Show("Please set the settings!");
                }
                
            }

            if (keyData == (Keys.Space))
            {
                if (_carInitiated)
                {
                    _manualOverride = true;
                    LapNr.Value = _carController.NewLap();
                }
            }

            if (keyData == Keys.R)
            {
                _carController = new CarController();
            }

            if (keyData == Keys.L)
            {
                tsmLapConfiguration.PerformClick();
            }
            return base.ProcessCmdKey(ref msg, keyData);
        }

        /// <summary>
        /// Sets icons in menu
        /// </summary>
        private void setIcons()
        {
            tsmInit.Image = Resources.init;
            tsmStartLogging.Image = Resources.StartLogging;
            tsmStopLogging.Image = Resources.StopLogging;
            stopToolStripMenuItem.Image = Resources.stop;
            tsmQuit.Image = Resources.Quit;

            tsmLapConfiguration.Image = Resources.Time;

            manualToolStripMenuItem.Image = Resources.settings;
            //defaultToolStripMenuItem.Image = Resources._default;
            importSettingsToolStripMenuItem.Image = Resources.folder;

            tsmGlobal.Image = Resources.global;
            tsmLogFileConfig.Image = Resources.logfile;
            tsmXbeeConfig.Image = Resources.XBEE;
            tsmArduinoConfig.Image = Resources.arduino;
            tsmSensorConfig.Image = Resources.sensor;

        }

        /// <summary>
        /// Starts logging
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tsmStartLoggin_Click(object sender, EventArgs e)
        {
            _carController.StartLogging();
        }

        /// <summary>
        /// Stops logging
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tsmStopLogging_Click(object sender, EventArgs e)
        {
            var t = _carController.StopLogging();
            if ( t == 1)
            {
                tsmStopLogging.Enabled = false;
                tsmStartLogging.Enabled = true;
            }
        }

        /// <summary>
        /// Starts configuration form - Sensor
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tsmSensorConfig_Click(object sender, EventArgs e)
        {
            _configForm.SwitchToTab(ConfigType.Sensor);
            _configForm.ShowDialog();
        }

        /// <summary>
        /// Starts configuration form - Log file
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tsmLogFileConfig_Click(object sender, EventArgs e)
        {
            //Start configuration form
            _configForm.SwitchToTab(ConfigType.Logfile);
            _configForm.ShowDialog();
        }

        /// <summary>
        /// Starts configuration form - Xbee
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tsmXbeeConfig_Click(object sender, EventArgs e)
        {
            //Start configuration form
            _configForm.SwitchToTab(ConfigType.XBee);
            _configForm.ShowDialog();
        }

        /// <summary>
        /// Starts configuration form - Arduino
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tsmArduinoConfig_Click(object sender, EventArgs e)
        {
            //Start configuration form
            _configForm.SwitchToTab(ConfigType.Arduino);
            _configForm.ShowDialog();
        }

        /// <summary>
        /// Starts configuration form - Global
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tsmGlobal_Click(object sender, EventArgs e)
        {
            _configForm.SwitchToTab(ConfigType.Global);
            _configForm.ShowDialog();
        }

        /// <summary>
        /// Inits software
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tsmInit_Click(object sender, EventArgs e)
        {
            if (_configForm.ReadyToBeInitiated)
            {
                _carController = new CarController();
                _carController.EventNewData += _carController_EventNewData;
                stopToolStripMenuItem.Enabled = true;
                tsmLapConfiguration.Enabled = true;
                tsmInit.Enabled = false;
                tsmStartLogging.Enabled = true;
                _carInitiated = true;
                timerTime.Enabled = true;
            }
            else
            {
                MessageBox.Show("Unable to initiate!\r\nYou will have to set the settings.");
            }
        }

        /// <summary>
        /// Stops software
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tsmStop_Click(object sender, EventArgs e)
        {
            _carController.CloseCOMPorts();
            _carController.StopLogging();
            _carController.StopLoggingError();
            _carController.StopOthers();
            _carController.EventNewData -= _carController_EventNewData;
            stopToolStripMenuItem.Enabled = false;
            tsmLapConfiguration.Enabled = false;
            tsmStartLogging.Enabled = false;
            tsmStopLogging.Enabled = false;

            _carController = null;

            tsmInit.Enabled = true;
        }

        /// <summary>
        /// New data event handler
        /// </summary>
        void _carController_EventNewData()
        {
            double distance = _carController.Distance;
            Amperage.Value = _carController.Amperage;
            distance *= 1000;
            DistanceMeter.Value = distance % 1000;
            DistanceKm.Value = (int)(distance / 1000);
            AdviseSpeed.Value = _carController.AdvisedSpeed;
            aMSpeed.Value = _carController.Speed;
            Speed.Value = _carController.Speed;
            Voltage.Value = _carController.Voltage;
            aMWatt.Value = _carController.Wattage;
            Watt.Value = _carController.Wattage;
            //Temperature.Value = _carController.Temperature;

            //Set section and lap value
            int sectionsPerLap = ConfigSingleton.Settings.SectionsPerLap;
            Section.Value = (_carController.CurrentSectionNumber % sectionsPerLap) + 1;

            if (!_manualOverride)
            {
                LapNr.Value = (int)(_carController.CurrentSectionNumber / sectionsPerLap) + 1;
            }

            if (_carController.BatteryOverheat && !_overheatMessageSend)
            {
                MessageBox.Show("Engine overheated! \r\nThe car wil now stop.");
                //Temperature.ForeColor = Color.YellowGreen;
                _overheatMessageSend = true;
            }
            else if (!_carController.BatteryOverheat && _overheatMessageSend)
            {
                //Temperature.ForeColor = Color.Red;
                _overheatMessageSend = false;
            }
        }

        /// <summary>
        /// Load default configuration
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void defaultToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                ConfigSingleton c = ConfigSingleton.Import<ConfigSingleton>(@"DefaultSettings.SEM");
                ConfigSingleton.Settings = c;
                _configForm.SetSettings();
                MessageBox.Show("Default settings loaded!");
            }
            catch (FileNotFoundException fileExeption)
            {
                if (DialogResult.Yes == MessageBox.Show("Error: " + fileExeption.Message + "\r\n\r\nDo you want to create a new settings file?", "Error: File not found", MessageBoxButtons.YesNo, MessageBoxIcon.Error))
                {
                    _configForm.SwitchToTab(ConfigType.Global);
                    _configForm.ShowDialog();
                }
            }
        }

        /// <summary>
        /// Imports settings from file
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void importSettingsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            openFileDialog.Filter = "SEM file (*.SEM)|*.SEM";
            if (DialogResult.OK == openFileDialog.ShowDialog())
            {
                try
                {
                    string loadPath = openFileDialog.FileName;
                    ConfigSingleton c = ConfigSingleton.Import<ConfigSingleton>(loadPath);
                    ConfigSingleton.Settings = c;
                    _configForm.SetSettings();
                    _configForm.ReadyToBeInitiated = true;
                    MessageBox.Show(Path.GetFileName(loadPath) + " loaded!");
                }
                catch (InvalidOperationException operationException)
                {
                    MessageBox.Show("Incorrect file: " + operationException.Message);
                }
            }
        }

        /// <summary>
        /// Starts lap configuration form
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tsmLapConfiguration_Click(object sender, EventArgs e)
        {
            if (_configForm.ReadyToBeInitiated)
            {
                _configLap.ShowDialog();
            }
            else
            {
                MessageBox.Show("Unable to start the lap configuration!\r\nYou will have to set the settings.");
            }
        }

        /// <summary>
        /// Starts logging
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tsmStartLogging_Click(object sender, EventArgs e)
        {
            _carController.StartLogging();
            tsmStartLogging.Enabled = false;
            tsmStopLogging.Enabled = true;
        }

        /// <summary>
        /// Opens config form
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void manualToolStripMenuItem_Click(object sender, EventArgs e)
        {
            _configForm.SwitchToTab(ConfigType.Global);
            _configForm.ShowDialog();
        }

        /// <summary>
        /// Quits the program
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void quitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (stopToolStripMenuItem.Enabled && tsmLapConfiguration.Enabled)
            {
                tsmStop_Click(null, EventArgs.Empty);
            }
            timerTime.Enabled = false;
            this.Close();
        }

        private void timerTime_Tick(object sender, EventArgs e)
        {
            if (_carController == null)
                return;

            List<TimeSpan> list = _carController.GetTimeData();

            CurrentTimeMin.Value = list[0].Minutes;
            CurrentTimeSec.Value = list[0].Seconds;
            PreviousTimeMin.Value = list[1].Minutes;
            PreviousTimeSec.Value = list[1].Seconds;
            AdviceTimeMin.Value = list[2].Minutes;
            AdviceTimeSec.Value = list[2].Seconds;
            TotalTimeMin.Value = list[3].Minutes;
            TotalTimeSec.Value = list[3].Seconds;
            TimeLeftMin.Value = list[4].Minutes;
            TimeLeftSec.Value = list[4].Seconds;
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (DialogResult.Yes == MessageBox.Show("Are you sure you want to close the application?", "Confirm", MessageBoxButtons.YesNo, MessageBoxIcon.Question))
            {
                if (stopToolStripMenuItem.Enabled && tsmLapConfiguration.Enabled)
                {
                    tsmStop_Click(null, EventArgs.Empty);
                }
                timerTime.Enabled = false;
            }
            else
            {
                e.Cancel = true;
            }
        }
    }
}
